#include "commit_file_command.h"
#include "service/backend_service.h"
#include "../database/database_manager.h"
#include "../database/file_system_status.h"
#include "command_executor.h"
#include <QDebug>
#include <QUrl>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QHttpMultiPart>
#include <QHttpPart>

CommitFileCommand::CommitFileCommand(QObject *parent)
    : BaseCommand(parent)
    , m_pendingDiskId("")
    , m_pendingFolderId("")
    , m_pendingSourceFileId("")
    , m_currentCommitSourceFileId("")
{
}

CommitFileCommand::~CommitFileCommand()
{
}

void CommitFileCommand::setNetworkAccessManager(QNetworkAccessManager *networkManager)
{
    // 如果之前已经设置了 networkManager，先断开旧的连接
    if (m_networkManager) {
        disconnect(m_networkManager, &QNetworkAccessManager::finished,
                   this, &CommitFileCommand::handleCommitFileResponse);
    }
    
    BaseCommand::setNetworkAccessManager(networkManager);
    
    // 连接网络请求完成信号
    if (m_networkManager) {
        connect(m_networkManager, &QNetworkAccessManager::finished,
                this, &CommitFileCommand::handleCommitFileResponse);
    }
}

bool CommitFileCommand::execute(const QString &diskId, const QString &folderId, const QString &sourceFileId)
{
    if (!isValid()) {
        qDebug() << "CommitFileCommand: BackendService 或 QNetworkAccessManager 未设置";
        emit commitFileCompleted(-1, "BackendService 或 QNetworkAccessManager 未设置");
        return false;
    }
    
    if (diskId.isEmpty() || folderId.isEmpty() || sourceFileId.isEmpty()) {
        qDebug() << "CommitFileCommand: 参数为空，diskId:" << diskId << "folderId:" << folderId << "sourceFileId:" << sourceFileId;
        emit commitFileCompleted(-1, "参数为空");
        return false;
    }
    
    // 检查是否有accessToken，如果没有则先获取
    if (!ensureAccessToken()) {
        // 如果没有选中的公司ID，无法获取accessToken
        if (!m_backendService || m_backendService->loadSelectedCompanyId().isEmpty()) {
            qDebug() << "CommitFileCommand: 没有选中的公司ID，无法获取accessToken";
            emit commitFileCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return false;
        }
        // 正在获取 token，保存待处理的参数
        m_pendingDiskId = diskId;
        m_pendingFolderId = folderId;
        m_pendingSourceFileId = sourceFileId;
        return true; // 返回true表示已发起获取token的请求
    }
    
    // 获取 accessToken
    QString accessToken = CommandExecutor::getAccessToken();
    
    // 获取 baseUrl
    QString baseUrl = getBaseUrl();
    
    // 构建提交文件的URL
    QString commitUrl = buildRequestUrl(baseUrl, diskId, folderId, sourceFileId);
    
    qDebug() << "CommitFileCommand: 开始提交文件，URL:" << commitUrl;
    
    // 保存当前提交的文件ID
    m_currentCommitSourceFileId = sourceFileId;
    
    // 创建网络请求
    // 注意：对于multipart请求，不能使用createRequest方法，因为它会设置Content-Type为application/json
    // 需要让Qt自动设置正确的multipart Content-Type（包括boundary参数）
    QNetworkRequest request;
    QUrl requestUrl(commitUrl);
    request.setUrl(requestUrl);
    request.setAttribute(QNetworkRequest::CustomVerbAttribute, "POST");
    request.setRawHeader("Accept", "application/json");
    request.setRawHeader("User-Agent", "CommitFileCommand/1.0");
    
    // 添加token到请求头
    addTokenToRequest(request, accessToken);
    
    // 确保accessToken已添加到请求头（双重检查）
    if (accessToken.isEmpty()) {
        qDebug() << "CommitFileCommand: 警告：accessToken为空，无法添加到请求头";
        emit commitFileCompleted(-1, "accessToken为空，无法提交文件");
        return false;
    }
    
    // 再次确认accessToken已添加到请求头
    request.setRawHeader("accessToken", accessToken.toUtf8());
    qDebug() << "CommitFileCommand: 已确认添加accessToken到请求头，token长度:" << accessToken.length();
    
    // 创建多部分数据
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    
    // 添加文件数据到multipart
    // 根据sourceFileId获取文件信息
    if (!m_databaseManager) {
        qDebug() << "CommitFileCommand: 数据库管理器未设置";
        emit commitFileCompleted(-1, "数据库管理器未设置");
        delete multiPart;
        return false;
    }
    
    KmsFile kmsFile = m_databaseManager->queryFileById(sourceFileId);
    if (kmsFile.id.isEmpty()) {
        qDebug() << "CommitFileCommand: 未找到文件记录，文件ID:" << sourceFileId;
        emit commitFileCompleted(-1, "未找到文件记录");
        delete multiPart;
        return false;
    }
    
    qDebug() << "CommitFileCommand: 找到文件记录，文件名:" << kmsFile.name << "本地路径:" << kmsFile.localFilePath;
    
    // 构建完整的本地文件路径
    QString workBase = getUserWorkBaseDir();
    QString localFilePath;
    
    // 优先使用 localFilePath 字段（相对于工作目录的路径）
    if (!kmsFile.localFilePath.isEmpty()) {
        localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.localFilePath);
        qDebug() << "CommitFileCommand: 使用 localFilePath 字段构建本地路径";
    } else {
        // 如果 localFilePath 为空，回退到根据文件夹路径和文件名构建
        // 从数据库获取文件夹路径
        QString folderPath = "";
        if (!kmsFile.folderId.isEmpty() && m_databaseManager) {
            // 通过查询文件夹路径来获取（使用PATH字段查询）
            QList<KmsFolder> allFolders = m_databaseManager->queryAllFolders();
            for (const auto &folder : allFolders) {
                if (folder.id == kmsFile.folderId) {
                    folderPath = folder.path;
                    break;
                }
            }
        }
        
        // 构建路径
        if (!folderPath.isEmpty()) {
            // 清理路径：移除开头的斜杠
            QString cleanFolderPath = folderPath;
            if (cleanFolderPath.startsWith('/')) {
                cleanFolderPath.remove(0, 1);
            }
            localFilePath = QDir::cleanPath(workBase + "/" + cleanFolderPath + "/" + kmsFile.name);
        } else {
            // 如果没有文件夹路径，只使用文件名
            localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.name);
        }
        qDebug() << "CommitFileCommand: 回退到根据文件夹路径和文件名构建本地路径";
    }
    
    qDebug() << "CommitFileCommand: 本地文件路径:" << localFilePath;
    
    // 检查文件是否存在
    QFile localFile(localFilePath);
    if (!localFile.exists()) {
        qDebug() << "CommitFileCommand: 本地文件不存在:" << localFilePath;
        emit commitFileCompleted(-1, "本地文件不存在");
        delete multiPart;
        return false;
    }
    
    // 读取文件内容
    if (!localFile.open(QIODevice::ReadOnly)) {
        qDebug() << "CommitFileCommand: 无法打开本地文件:" << localFile.errorString();
        emit commitFileCompleted(-1, "无法打开本地文件");
        delete multiPart;
        return false;
    }
    
    QByteArray fileContent = localFile.readAll();
    localFile.close();
    
    qDebug() << "CommitFileCommand: 文件内容大小:" << fileContent.size() << "字节";
    
    // 创建文件部分
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, 
                      QVariant("form-data; name=\"files\"; filename=\"" + kmsFile.name + "\""));
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
    filePart.setBody(fileContent);
    
    multiPart->append(filePart);
    
    // 发送POST请求
    QNetworkReply *reply = m_networkManager->post(request, multiPart);
    multiPart->setParent(reply); // 确保在reply删除时也删除multiPart
    
    // 让QNetworkAccessManager自动设置正确的Content-Type头
    // 包括boundary参数
    
    // 设置请求类型标识
    reply->setProperty("requestType", "commitFile");
    
    // 初始化响应数据存储
    m_responseData[reply] = QByteArray();
    
    // 连接readyRead信号以累积响应数据（用于处理分块传输编码）
    connect(reply, &QNetworkReply::readyRead, this, &CommitFileCommand::handleReadyRead);
    
    qDebug() << "CommitFileCommand: 文件提交请求已发送";
    
    return true;
}

void CommitFileCommand::handleCommitFileResponse(QNetworkReply *reply)
{
    // 检查对象是否仍然有效（可能在信号排队期间被销毁）
    if (!isValid()) {
        qDebug() << "CommitFileCommand: 对象已被销毁，忽略响应";
        if (reply) {
            reply->deleteLater();
        }
        return;
    }
    
    if (!reply) {
        qDebug() << "CommitFileCommand: 文件提交响应为空";
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit commitFileCompleted(-1, "文件提交响应为空");
        }
        return;
    }
    
    QString requestType = reply->property("requestType").toString();
    if (requestType != "commitFile") {
        // 不是文件提交请求，忽略
        reply->deleteLater();
        return;
    }
    
    // 检查是否已经处理过这个响应
    if (reply->property("processed").toBool()) {
        qDebug() << "CommitFileCommand: 响应已经被处理过，跳过";
        reply->deleteLater();
        return;
    }
    
    // 标记为已处理
    reply->setProperty("processed", true);
    
    qDebug() << "CommitFileCommand: 处理文件提交响应，reply对象:" << reply;
    
    // 打印详细的响应信息
    int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "CommitFileCommand: HTTP状态码:" << httpStatusCode;
    qDebug() << "CommitFileCommand: 响应头信息:" << reply->rawHeaderPairs();
    qDebug() << "CommitFileCommand: 响应错误:" << reply->error() << reply->errorString();
    qDebug() << "CommitFileCommand: 可用字节数:" << reply->bytesAvailable();
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "CommitFileCommand: 文件提交失败:" << reply->errorString();
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit commitFileCompleted(reply->error(), "提交失败: " + reply->errorString());
        }
        reply->deleteLater();
        return;
    }
    
    // 对于分块传输编码（chunked），数据可能通过readyRead信号累积
    // 首先尝试从累积的数据中读取
    QByteArray data = m_responseData.take(reply);
    
    // 如果累积的数据为空，尝试直接从reply读取（兼容非分块传输）
    if (data.isEmpty()) {
        data = reply->readAll();
        qDebug() << "CommitFileCommand: 从reply直接读取数据，长度:" << data.length();
    } else {
        qDebug() << "CommitFileCommand: 从累积数据读取，长度:" << data.length();
    }
    
    qDebug() << "CommitFileCommand: 文件提交响应原始数据长度:" << data.length();
    qDebug() << "CommitFileCommand: 文件提交响应原始数据:" << data;
    
    // 检查数据是否为空
    if (data.isEmpty()) {
        qDebug() << "CommitFileCommand: 警告：读取到的响应数据为空";
        if (httpStatusCode == 200 || httpStatusCode == 0) {
            if (isValid()) {
                emit commitFileCompleted(0, "文件提交成功（无响应体）");
            }
        } else {
            if (isValid()) {
                emit commitFileCompleted(-1, QString("文件提交失败，HTTP状态码: %1").arg(httpStatusCode));
            }
        }
        reply->deleteLater();
        return;
    }
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "CommitFileCommand: JSON解析错误:" << parseError.errorString();
        qDebug() << "CommitFileCommand: 错误位置:" << parseError.offset;
        if (isValid()) {
            emit commitFileCompleted(-1, "响应数据格式错误: " + parseError.errorString());
        }
        reply->deleteLater();
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "CommitFileCommand: 响应数据不是有效的JSON对象";
        if (isValid()) {
            emit commitFileCompleted(-1, "响应数据格式错误：不是有效的JSON对象");
        }
        reply->deleteLater();
        return;
    }
    
    QJsonObject response = doc.object();
    qDebug() << "CommitFileCommand: 文件提交响应:" << response;
    
    // 再次检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "CommitFileCommand: 对象已被销毁，忽略响应解析";
        reply->deleteLater();
        return;
    }
    
    parseCommitFileResponse(response);
    
    reply->deleteLater();
}

void CommitFileCommand::handleReadyRead()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        return;
    }
    
    QString requestType = reply->property("requestType").toString();
    if (requestType != "commitFile") {
        // 不是文件提交请求，忽略
        return;
    }
    
    // 读取可用数据并累积
    QByteArray newData = reply->readAll();
    if (!newData.isEmpty()) {
        m_responseData[reply] += newData;
        qDebug() << "CommitFileCommand: 累积响应数据，当前总长度:" << m_responseData[reply].length();
    }
}

void CommitFileCommand::parseCommitFileResponse(const QJsonObject &response)
{
    // 检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "CommitFileCommand: 对象已被销毁，忽略响应解析";
        return;
    }
    
    // 添加完整的响应数据日志
    qDebug() << "CommitFileCommand: 文件提交响应完整数据:" << response;
    qDebug() << "CommitFileCommand: 文件提交响应键列表:" << response.keys();
    
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "CommitFileCommand: 文件提交响应 - errcode:" << errcode << "errmsg:" << errmsg;
    
    if (errcode == 0) {
        qDebug() << "CommitFileCommand: 文件提交成功:" << errmsg;
        
        // 更新文件状态为已同步(1)
        if (!m_currentCommitSourceFileId.isEmpty()) {
            qDebug() << "CommitFileCommand: 文件提交成功，更新文件状态，文件ID:" << m_currentCommitSourceFileId;
            // 直接更新数据库
            if (m_databaseManager && isValid()) {
                // m_databaseManager->updateFileStatus(m_currentCommitSourceFileId, FileSystemStatus::SYNCED);
                
                // 更新文件信息，通过 response.data 更新文件的 version 和 checksum
                QJsonArray dataArray = response["data"].toArray();
                if (!dataArray.isEmpty()) {
                    QJsonObject fileData = dataArray[0].toObject();
                    qDebug() << "CommitFileCommand: 文件提交响应 - data:" << fileData;
                    
                    // 提取 version 和 checksum
                    int version = fileData["version"].toInt();
                    QString checksum = fileData["checksum"].toString();
                    
                    qDebug() << "CommitFileCommand: 更新文件信息 - version:" << version << "checksum:" << checksum;
                    
                    // 查询当前文件信息
                    KmsFile currentFile = m_databaseManager->queryFileById(m_currentCommitSourceFileId);
                    if (!currentFile.id.isEmpty()) {
                        // 更新 version 和 checksum
                        currentFile.version = version;
                        currentFile.checksum = checksum;
                        currentFile.status = FileSystemStatus::SYNCED;
                        
                        // 更新文件信息到数据库
                        if (m_databaseManager->updateFile(currentFile)) {
                            qDebug() << "CommitFileCommand: 成功更新文件 version 和 checksum";
                        } else {
                            qDebug() << "CommitFileCommand: 更新文件 version 和 checksum 失败";
                        }
                    } else {
                        qDebug() << "CommitFileCommand: 未找到文件记录，无法更新 version 和 checksum";
                    }
                } else {
                    qDebug() << "CommitFileCommand: 响应 data 数组为空，无法更新文件信息";
                }
            }
            m_currentCommitSourceFileId.clear(); // 清除当前提交的文件ID
        }
        
        // 发送提交完成信号
        if (isValid()) {
            emit commitFileCompleted(0, "文件提交成功");
        }
        
    } else {
        qDebug() << "CommitFileCommand: 文件提交失败:" << errmsg;
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit commitFileCompleted(errcode, errmsg);
        }
    }
}

QString CommitFileCommand::buildRequestUrl(const QString &baseUrl, const QString &diskId, const QString &folderId, const QString &sourceFileId)
{
    QString commitUrl = baseUrl + "/kms/api/kms/sync/commitFile";
    commitUrl += "?diskId=" + diskId;
    commitUrl += "&folderId=" + folderId;
    commitUrl += "&sourceFileId=" + sourceFileId;
    return commitUrl;
}

QString CommitFileCommand::getUserWorkBaseDir() const
{
    if (!m_backendService) {
        return QString();
    }
    // 通过 BackendService 获取用户工作目录
    return m_backendService->getUserWorkBaseDir();
}

